package com.smartstate.dataManagement.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smartstate.EnvironmentMonitor.vo.ResultVO;
import com.smartstate.dataManagement.config.redis.RedisService;
import com.smartstate.dataManagement.controller.TestController;
import com.smartstate.dataManagement.dto.EnergyDTO;
import com.smartstate.dataManagement.dto.ObjMoudelDTO;
import com.smartstate.dataManagement.dto.PageDTO;
import com.smartstate.dataManagement.dto.common.TreeNode;
import com.smartstate.dataManagement.entity.ObjMoudel;
import com.smartstate.dataManagement.entity.Rate;
import com.smartstate.dataManagement.exception.ErrorEnums;
import com.smartstate.dataManagement.exception.MyRException;
import com.smartstate.dataManagement.mapper.ObjMoudelMapper;
import com.smartstate.dataManagement.service.ObjMoudelService;
import com.smartstate.dataManagement.util.MyExpressionUtil;
import com.smartstate.dataManagement.util.ObjDemoUtils;
import com.smartstate.dataManagement.vo.EquipmentForTreeVO;
import com.smartstate.dataManagement.vo.ObjMoudelNameVo;
import com.smartstate.dataManagement.vo.ObjMoudelTwoVo;
import com.smartstate.dataManagement.vo.ObjmiddleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.Resource;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>楼宇</p>
 * <p>@Author 陈永杰</p>
 * <p>@Date: 2022/8/17</p>
 * <p>@Time: 22:06</p>
 * <p>@version 1.0 <p>
 */
@Transactional
@Service
@Slf4j
public class ObjMoudelServiceImpl extends ServiceImpl<ObjMoudelMapper, ObjMoudel> implements ObjMoudelService {

    @Resource
    private ObjMoudelMapper objMoudelMapper;

    @Value("${environmental.monitoring}")
    private String url;

    @Override
    public Page<ObjMoudel> queryAllPageByDTO(PageDTO pageDTO) {
        return null;
    }



    /**
     * 楼宇树结构
     *
     * @return
     */
    @Override
    public List<TreeNode> selectMoudel(String type) {
        List<TreeNode> nodeList = objMoudelMapper.selectModelTree(type);
        List<EquipmentForTreeVO> equipmentList = objMoudelMapper.selectTree();
        return ObjDemoUtils.getTreeNode(nodeList, equipmentList);
    }

    @Override
    public int updatePhoto(@RequestParam(value = "file", required = false) MultipartFile file, ObjMoudel objMoudel) {
        TestController ts = new TestController();
        ResultVO resultVO = ts.uploadImage(file, url);
        objMoudel.setCreateTime(new Date());
        String urls = url.substring(17);
        objMoudel.setPhoto(urls + resultVO.getData());
        return objMoudelMapper.updatePhoto(objMoudel.getId(), objMoudel.getPhoto());
    }

    //查出所有父子级
    @Override
    public List<Map<String, String>> selectMetering(EnergyDTO item) {
        Map mapElect = new HashMap();
        List<Map<String, String>> children = new ArrayList<>();
        String electricitys = null;
        String waters = null;
        String naturals = null;
        String steams = null;

        ObjMoudelTwoVo objMoudelTwoVo = objMoudelMapper.selectMetering(item);
        if (objMoudelTwoVo != null) {
            List<Map> lists = JSON.parseArray(objMoudelTwoVo.getMetering(), Map.class);
            if (lists != null) {
                for (Map mapList : lists) {
                    if (mapList.get("电") != null && !mapList.get("电").equals("")) {
                        electricitys = (String) mapList.get("电");
                        mapElect.put("电", electricitys);

                    } else if (mapList.get("水") != null && !mapList.get("水").equals("")) {
                        waters = (String) mapList.get("水");
                        mapElect.put("水", waters);
                    } else if (mapList.get("天然气") != null && !mapList.get("天然气").equals("")) {
                        naturals = (String) mapList.get("天然气");
                        mapElect.put("天然气", naturals);
                    } else if (mapList.get("蒸汽") != null && !mapList.get("蒸汽").equals("")) {
                        steams = (String) mapList.get("蒸汽");
                        mapElect.put("蒸汽", steams);
                    }

                }
            }
            mapElect.put("id", objMoudelTwoVo.getId());
            mapElect.put("name", objMoudelTwoVo.getName());
            mapElect.put("parentId", objMoudelTwoVo.getParentId());
            mapElect.put("type", objMoudelTwoVo.getType());
//            mapElect.put("children", children);
            children.add(mapElect);
            metering(children, objMoudelTwoVo.getId());
        }
        return children;
    }

    private void metering(List<Map<String, String>> children, String id) {
        String electricitys = null;
        String waters = null;
        String naturals = null;
        String steams = null;
        //查询第一层的根节点  下的子级
        List<ObjMoudelTwoVo> objMoudelTwoVos = objMoudelMapper.selectMeteringAll(id);
        //如果下面没有子级 就返回
        if (objMoudelTwoVos.size() != 0) {
            //如果根节点有子级 就递归遍历 找下面的子级 自己调自己方法
            for (ObjMoudelTwoVo objMoudelTwoVo : objMoudelTwoVos) {
                objMoudelTwoVo.getId();
                objMoudelTwoVo.getName();
                objMoudelTwoVo.getParentId();
                Map mapElect = new HashMap();

                List<Map> lists = JSON.parseArray(objMoudelTwoVo.getMetering(), Map.class);
                if (lists != null) {
                    for (Map mapList : lists) {
                        if (mapList.get("电") != null && !"".equals(mapList.get("电"))) {
                            electricitys = (String) mapList.get("电");
                            mapElect.put("电", electricitys);
                        } else if (mapList.get("水") != null && !"".equals(mapList.get("水"))) {
                            waters = (String) mapList.get("水");
                            mapElect.put("水", waters);
                        } else if (mapList.get("天然气") != null && !"".equals(mapList.get("天然气"))) {
                            naturals = (String) mapList.get("天然气");
                            mapElect.put("天然气", naturals);
                        } else if (mapList.get("蒸汽") != null && !"".equals(mapList.get("蒸汽"))) {
                            steams = (String) mapList.get("蒸汽");
                            mapElect.put("蒸汽", steams);
                        }

                    }
                }
                mapElect.put("id", objMoudelTwoVo.getId());
                mapElect.put("name", objMoudelTwoVo.getName());
                mapElect.put("parentId", objMoudelTwoVo.getParentId());
                mapElect.put("type", objMoudelTwoVo.getType());
//                mapElect.put("children", children);
                children.add(mapElect);
//                List<Map<String, ObjMoudel>> list = (List<Map<String, ObjMoudel>>)map.get("children");
//                list.add(mapElect);
                metering(children, objMoudelTwoVo.getId());
            }
        }

    }


    //组装树
    @Override
    public Map<String, Object> selectPowerTree(EnergyDTO item) {
        Map mapElect = new HashMap();
        List<Map<String, Object>> children = new ArrayList<>();
        String electricitys = null;
        String waters = null;
        String naturals = null;
        String steams = null;

        ObjMoudelTwoVo objMoudelTwoVo = objMoudelMapper.selectMetering(item);
        List<Map> lists = JSON.parseArray(objMoudelTwoVo.getMetering(), Map.class);
        if (lists != null) {
            for (Map mapList : lists) {
                if (mapList.get("电") != null && !mapList.get("电").equals("")) {
                    electricitys = (String) mapList.get("电");
                    mapElect.put("电", electricitys);

                } else if (mapList.get("水") != null && !mapList.get("水").equals("")) {
                    waters = (String) mapList.get("水");
                    mapElect.put("水", waters);
                } else if (mapList.get("天然气") != null && !mapList.get("天然气").equals("")) {
                    naturals = (String) mapList.get("天然气");
                    mapElect.put("天然气", naturals);
                } else if (mapList.get("蒸汽") != null && !mapList.get("蒸汽").equals("")) {
                    steams = (String) mapList.get("蒸汽");
                    mapElect.put("蒸汽", steams);
                }

            }
        }
        mapElect.put("id", objMoudelTwoVo.getId());
        mapElect.put("name", objMoudelTwoVo.getName());
        mapElect.put("parentId", objMoudelTwoVo.getParentId());
        mapElect.put("type", objMoudelTwoVo.getType());
        mapElect.put("children", children);
        meteringTree(mapElect, objMoudelTwoVo.getId());

        return mapElect;
    }

    private void meteringTree(Map map, String id) {
        String electricitys = null;
        String waters = null;
        String naturals = null;
        String steams = null;
        //查询第一层的根节点  下的子级
        List<ObjMoudelTwoVo> objMoudelTwoVos = objMoudelMapper.selectMeteringAll(id);
        //如果下面没有子级 就返回
        if (objMoudelTwoVos.size() != 0) {
            //如果根节点有子级 就递归遍历 找下面的子级 自己调自己方法
            for (ObjMoudelTwoVo objMoudelTwoVo : objMoudelTwoVos) {
                List<Map<String, Object>> children = new ArrayList<>();
                objMoudelTwoVo.getId();
                objMoudelTwoVo.getName();
                objMoudelTwoVo.getParentId();
                Map mapElect = new HashMap();
                List<Map> lists = JSON.parseArray(objMoudelTwoVo.getMetering(), Map.class);
                if (lists != null) {
                    for (Map mapList : lists) {
                        if (mapList.get("电") != null && !mapList.get("电").equals("")) {
                            electricitys = (String) mapList.get("电");
                            mapElect.put("电", electricitys);

                        } else if (mapList.get("水") != null && !mapList.get("水").equals("")) {
                            waters = (String) mapList.get("水");
                            mapElect.put("水", waters);
                        } else if (mapList.get("天然气") != null && !mapList.get("天然气").equals("")) {
                            naturals = (String) mapList.get("天然气");
                            mapElect.put("天然气", naturals);
                        } else if (mapList.get("蒸汽") != null && !mapList.get("蒸汽").equals("")) {
                            steams = (String) mapList.get("蒸汽");
                            mapElect.put("蒸汽", steams);
                        }

                    }
                }
                mapElect.put("id", objMoudelTwoVo.getId());
                mapElect.put("name", objMoudelTwoVo.getName());
                mapElect.put("parentId", objMoudelTwoVo.getParentId());
                mapElect.put("type", objMoudelTwoVo.getType());
                mapElect.put("children", children);
                List<Map<String, Object>> list = (List<Map<String, Object>>) map.get("children");
                list.add(mapElect);
                meteringTree(mapElect, objMoudelTwoVo.getId());
            }
        }

    }


    boolean verifyRegix(String orgData) {
        String pattern2 = "\\$\\{[\\d|\\w]*\\}";
        Pattern  p2 = Pattern.compile(pattern2);
        Matcher m2 = p2.matcher(orgData);
        int i = 0;
        while(m2.find()){
            i++;
        }

        String pattern1 = "\\$";
        p2 = Pattern.compile(pattern1);
        m2 = p2.matcher(orgData);
        int b = 0;
        while(m2.find()){
            b++;
        }
        return i == b;
    }

    @Override
    public int updateMetering(String id, JSONArray metering) {

        JSONArray objects = JSONArray.parseArray(metering.toString());
        boolean s =true;
        for (Object object : objects) {
            if (!verifyRegix(object.toString())){
                s= false;
                break;
            }
        }
        if (s){
            boolean a =true;
            for (Object object : objects) {
                Map map =  (Map) object;

                if (map.get("水")!=null && !"".equals(map.get("水"))){
                    String  water = (String)map.get("水");
                    List<String> waterParams = MyExpressionUtil.getExpressionParams(water);
                    int i = objMoudelMapper.selectDeviceIdAll(waterParams);
                    if (i!=waterParams.size()){
                        a=false;
                    }
                }
                if (map.get("电")!=null && !"".equals(map.get("电"))){
                    String electricity =(String) map.get("电");
                    List<String> expressionParams = MyExpressionUtil.getExpressionParams(electricity);
                    int i = objMoudelMapper.selectDeviceIdAll(expressionParams);
                    if (i!=expressionParams.size()){
                        a=false;
                    }
                }

                if (map.get("天然气")!=null && !"".equals(map.get("天然气"))){
                    String  natural =(String) map.get("天然气");
                    List<String> naturalParams = MyExpressionUtil.getExpressionParams(natural);
                    int i = objMoudelMapper.selectDeviceIdAll(naturalParams);
                    if (i!=naturalParams.size()){
                        a=false;
                    }
                }

                if (map.get("蒸汽")!=null && !"".equals(map.get("蒸汽"))){
                    String  steam = (String)map.get("蒸汽");
                    List<String> steamParams = MyExpressionUtil.getExpressionParams(steam);
                    int i = objMoudelMapper.selectDeviceIdAll(steamParams);
                    if (i!=steamParams.size()){
                        a=false;
                    }
                }
            }
            if (a){
                //添加进数据库
                return objMoudelMapper.updateMetering(id,objects.toString());
            }else {
                throw new MyRException(ErrorEnums.INEXISTENCE_ERROR);
            }
        }else {
            //公式错误，返回异常
            throw  new MyRException(ErrorEnums.FORMULA_ERROR);
        }
    }



                /**
                 * 添加设备 和楼宇 中间表
                 *
                 * @param
                 */
    @Override
    public int addObjmiddle(ObjmiddleVo objmiddleVo) {
        return objMoudelMapper.addObjmiddle(objmiddleVo);
    }


    /**
     * 新增节点或修改节点 id=0新建根节点，id!=0修改或添加子节点
     *
     * @param
     */
    @Override
    public boolean addOrUpdateNode(ObjMoudelDTO objMoudelDTO) {
        ObjMoudel objMoudel = new ObjMoudel();
//        objMoudelDTO对于属性赋值到objMoudel
        BeanUtils.copyProperties(objMoudelDTO, objMoudel);
////        修改节点
        if (objMoudel.getType() == null)
            return objMoudelMapper.updateById(objMoudel) > 0;
//        添加根节点
        if ("0".equals(objMoudel.getId())) {
            log.info("123   "+String.valueOf(objMoudelMapper.queryType(objMoudelDTO.getType())));
            if (objMoudelMapper.queryType(objMoudelDTO.getType()).size() > 0)
                return false;
        }
        objMoudel.setCreateTime(new Date());
        objMoudel.setParentId(objMoudelDTO.getId());
        objMoudel.setId(UUID.randomUUID().toString());
        objMoudel.setUpdateTime(new Date());
        return objMoudelMapper.insert(objMoudel) > 0;
    }

    /**
     * 根据list中的节点id集合删除对于节点
     *
     * @param list
     * @return
     */
    @Override
    public boolean delectNode(List<String> list) {
        AtomicBoolean flag = new AtomicBoolean(false);
        list.forEach((s) -> {
            flag.set(delectByQueryId(s));
        });
        return flag.get();
    }

    /**
     * 查图纸
     * @param id
     * @return
     */
    @Override
    public ObjMoudel selectPhoto(String id) {
        return objMoudelMapper.selectPhoto(id);
    }

    /**
     * 查所有楼层所携带的设备 拿出楼层名 和设备deviceId
     * @return
     */
    @Override
    public List<ObjMoudelNameVo> getObjMoudelName() {
        return objMoudelMapper.getObjMoudelName();
    }

    /**
     * 递归删除该id对应的子节点
     *
     * @param id
     * @return
     */
    public boolean delectByQueryId(String id) {
        List<String> ids = objMoudelMapper.queryId(id);
//        删除图片
        String imgPath = objMoudelMapper.queryImage(id);
        if (imgPath != null){
            delectImage(imgPath);
        }
        objMoudelMapper.deleteById(id);
        objMoudelMapper.deleteObjmiddleById(id);
        if (ids == null || ids.size() == 0) {
            return true;
        }
        ids.forEach((s) -> {
            delectByQueryId(s);
        });
        return true;
    }

    /**
     * 删除节点对应图片
     * @param imgPath
     * @return
     */
    public void delectImage(String imgPath){
//        String path = url.substring(17);
        String path = "F:\\新建文件夹";
        imgPath = path + imgPath;
        File file = new File(imgPath);
        //判断文件是否存在
        if (file.exists() == true){
            log.info(file.delete() == true ? "图片删除成功" : "图片删除失败");
        }else {
            log.info("图片不存在");
        }
    }

}